﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Tracy.DataModel;
using System.Xml;
using Tracy;
using SharedLib.Helpers;
using SharedLib;
using System.IO;

namespace TracyGUI.Model
{
    class ImportExportManager
    {
        public static event EventHandler<GenericEventArgs<Resource>> ResourceFound;
        public void ImportPhysicalFiles(string entryName, string savePath, List<string> filenames)
        {
            if (!String.IsNullOrEmpty(entryName) && !String.IsNullOrEmpty(savePath) && filenames != null && filenames.Count > 0)
            {
                Entry newEntry = new Entry(entryName);
                newEntry.Name = entryName;
                newEntry.TracingDisabled = true;
                newEntry.SavePath = savePath;
                TracyFacade.Instance.EntryProvider.AddItem(newEntry);

                List<MediaFile> fileList = new List<MediaFile>();
                foreach (string fileFullName in filenames)
                {
                    Resource res = new Resource();
                    res.Entry = newEntry;
                    res.Created = File.GetCreationTime(fileFullName).ToString();
                    res.Title = Path.GetFileName(fileFullName);
                    res.Status = "Sent"; //TODO: use other status

                    TracyFacade.Instance.ResourceProvider.AddItem(res);

                    MediaFile file = new MediaFile();
                    file.Resource = res;
                    file.FileName = res.Title;
                    file.Status = "Watched";
                    if (MediaFile.IsVisible(file.FileName)) file.Visible = "true";
                    int prefixLength = savePath.Length + 1;
                    file.Location = fileFullName.Substring(prefixLength, fileFullName.Length - prefixLength - file.FileName.Length);
                    fileList.Add(file);
                }
                
                TracyFacade.Instance.MediaFileProvider.AddItems(fileList);
            }
        }
        public XmlDocument ExportEntries(List<Entry> entries)
        {
            XmlDocument doc = new XmlDocument();
            XmlElement entryLiseNode = doc.CreateElement("entries");
            foreach (Entry entry in entries)
            {
                //Clear save path info
                entry.SavePath = null;

                XmlNode entryNode = entry.ToXmlNode(doc);

                //Export Filter Set
                XmlNode filterSetListNode = doc.CreateElement("filter-sets");
                foreach (FilterSet filterSet in TracyFacade.Instance.FilterManager.FilterProvider.GetFilterSets(entry))
                {
                    filterSetListNode.AppendChild(filterSet.ToXmlNode(doc));
                }
                entryNode.AppendChild(filterSetListNode);

                //Export Resource
                XmlNode resourceListNode = doc.CreateElement("resources");
                foreach (Resource res in TracyFacade.Instance.ResourceProvider.GetItemsByEntry(entry))
                {
                    if (!String.IsNullOrEmpty(res.Url))
                    {
                        res.Status = "New";
                        res.Entry = null;
                        resourceListNode.AppendChild(res.ToXmlNode(doc));
                    }
                }
                entryNode.AppendChild(resourceListNode);

                //Export Tags
                XmlNode tagListNode = doc.CreateElement("tags");
                foreach (Tag tag in TracyFacade.Instance.TagManager.GetTags(entry))
                {
                    tagListNode.AppendChild(tag.ToXmlNode(doc));
                }
                entryNode.AppendChild(tagListNode);

                entryLiseNode.AppendChild(entryNode);
            }
            doc.AppendChild(entryLiseNode);
            return doc;
        }

        public void ImportEntries(List<Entry> entries, string defaultPath, XmlDocument source){
            foreach (Entry entry in entries)
            {
                //Update entry
                XmlNode entryNode = source.SelectSingleNode(String.Format("/entries/entry[@id='{0}']", entry.ID));
                if (entryNode != null)
                {
                    Entry existingEntry = null;
                    if (entry.Properties.ContainsKey("original-id")) existingEntry = TracyFacade.Instance.EntryProvider.GetItemByID(entry.Properties["original-id"]);

                    if (existingEntry == null) //add entry
                    {
                        entry.Attributes.Remove("id"); //Generate new entry id and save path
                        entry.SavePath = defaultPath + "\\" + StringHelper.RemoveInvalidCharFromFileName(entry.Name);
                        TracyFacade.Instance.EntryProvider.AddItem(entry);
                    }
                    else //update entry
                    {
                        entry.Attributes["id"] = existingEntry.ID; //Use original ID and save path
                        entry.SavePath = existingEntry.SavePath;
                        TracyFacade.Instance.EntryProvider.UpdateItem(entry);
                    }

                    //Update Filter Sets
                    List<FilterSet> filterSets = new List<FilterSet>();
                    List<FilterSet> existingFilterSets = null;
                    if (existingEntry != null)
                    {
                        existingFilterSets = TracyFacade.Instance.FilterManager.FilterProvider.GetFilterSets(entry);
                        filterSets.AddRange(existingFilterSets);
                    }
                    foreach (XmlNode filterSetNode in entryNode.SelectNodes("filter-sets/filter-set"))
                    {
                        FilterSet fs = new FilterSet(filterSetNode);
                        bool willAdd = true;
                        if (existingFilterSets != null)
                        {
                            foreach (FilterSet existingFS in existingFilterSets) //Remove duplicated filtersets
                            {
                                if (fs.Equals(existingFS))
                                {
                                    willAdd = false;
                                    break;
                                }
                            }
                        }
                        if (willAdd) filterSets.Add(fs);
                    }
                    TracyFacade.Instance.FilterManager.FilterProvider.SetFilterSets(filterSets, entry);

                    //Update Resources
                    foreach (XmlNode resNode in entryNode.SelectNodes("resources/resource"))
                    {
                        Resource res = new Resource(resNode);
                        if (existingEntry == null || !TracyFacade.Instance.ResourceProvider.IsResourceExisting(res))
                        {
                            res.Entry = entry;
                            ResourceFound.InvokeEvent(this, new GenericEventArgs<Resource>(res));
                        }
                    }

                    //Update Tags
                    List<Tag> tags = new List<Tag>();
                    List<Tag> existingTags = null;
                    if (existingEntry != null)
                    {
                        existingTags = TracyFacade.Instance.TagManager.GetTags(entry);
                    }
                    foreach (XmlNode tagNode in entryNode.SelectNodes("tags/tag"))
                    {
                        Tag tag = new Tag(tagNode);
                        bool willAdd = true;
                        if (existingTags != null)
                        {
                            foreach (Tag existingTag in existingTags)//Remove duplicated tags
                            {
                                if (tag.Equals(existingTag))
                                {
                                    willAdd = false;
                                    break;
                                }
                            }
                        }
                        if (willAdd) tags.Add(tag);
                    }

                    //Only add new tags
                    foreach(Tag tag in tags) TracyFacade.Instance.TagManager.AssignTag(entry, tag);
                }
            }
        }
    }
}
